<template>
  <div class="home">
    <!-- 上面的搜索条件 -->
    <div class="home-option">
      <t-card size="small" class="w-full">
        <div class="flex justify-between items-center">
          <t-space class="items-center" size="small">
            <!-- 输入框 -->
            <t-input
              v-model="keyword"
              placeholder="请输入索引名称"
              style="width: clamp(200px, 45vw, 500px)"
              allow-clear
            ></t-input>
            <t-select v-model="order" placeholder="索引排序" style="width: 120px">
              <t-option :value="OrderType.NAME_ASC" label="名称正序">名称正序</t-option>
              <t-option :value="OrderType.NAME_DESC" label="名称倒序" />
              <t-option :value="OrderType.SIZE_ASC" label="大小正序" />
              <t-option :value="OrderType.SIZE_DESC" label="大小倒序" />
              <t-option :value="OrderType.DOCS_ASC" label="文档正序" />
              <t-option :value="OrderType.DOCS_DESC" label="文档倒序" />
            </t-select>
            <t-select v-model="status" type="button">
              <t-option :value="Status.NONE" label="忽略" />
              <t-option :value="Status.OPEN" label="开启" />
              <t-option :value="Status.CLOSE" label="关闭" />
            </t-select>
          </t-space>
          <!-- 新增索引 -->
          <t-button theme="primary" :disabled="!url" @click="indexAdd()"> 新建 </t-button>
        </div>
      </t-card>
    </div>
    <!-- 索引容器 -->
    <div ref="homeContainer" class="home-container">
      <t-list split class="home-index-items" :scroll="virtualListProps">
        <t-list-item v-for="row in virtualRows" :key="row.key">
          <group-header
            v-if="row.type === 'group'"
            :name="row.group"
            :count="row.count"
            :collapsed="collapsedGroups.has(row.group)"
            @toggle="toggleGroup(row.group)"
          />
          <index-item v-else :index="row.index" />
        </t-list-item>
      </t-list>
      <a-back-top target-container=".home-container .arco-scrollbar-container" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { TScroll } from "tdesign-vue-next";
import { useIndexStore, useUrlStore } from "@/store";
import IndexItem from "./components/index-item.vue";
import GroupHeader from "./components/group-header.vue";
import { useFuse } from "@vueuse/integrations/useFuse";
import { OrderType, Status, useHomeStore } from "@/store/components/HomeStore";
import { indexAdd } from "@/page/home/components/IndexAdd";
import type { IndexItem as IndexItemType } from "$/elasticsearch-client";

const size = useWindowSize();
// 容器引用与尺寸，用于精确计算虚拟列表高度
const homeContainer = ref<HTMLElement | null>(null);
const containerSize = useElementSize(homeContainer);

const keyword = useHomeStore().keyword;
const order = useHomeStore().order;
const status = useHomeStore().status;

const url = computed(() => useUrlStore().url);
const virtualListProps = computed<TScroll>(() => ({
  type: "virtual",
  rowHeight: 80,
  bufferSize: 10,
  threshold: 10,
  // 优先使用容器实际高度，容器未就绪时使用窗口高度的估算值
  height: containerSize.height.value || Math.max(0, size.height.value - 56)
}));
const indices = computed(() => {
  useIndexStore().sort(order.value);
  let indices = useIndexStore().indices;
  // 状态
  if (status.value !== Status.NONE) {
    if (status.value === Status.OPEN) {
      indices = indices.filter((index) => index.state === "open");
    } else if (status.value === Status.CLOSE) {
      indices = indices.filter((index) => index.state === "close");
    }
  }
  // 排序
  return indices;
});

const { results } = useFuse(keyword, indices, {
  matchAllWhenSearchEmpty: true,
  fuseOptions: {
    keys: [
      {
        name: "name"
      },
      {
        name: "alias"
      }
    ]
  }
});

const items = computed(() => {
  return results.value.map((result) => result.item);
});

// 分组折叠集合
const collapsedGroups = ref<Set<string>>(new Set());

function toggleGroup(group: string) {
  const set = collapsedGroups.value;
  if (set.has(group)) {
    set.delete(group);
  } else {
    set.add(group);
  }
  // 触发响应
  collapsedGroups.value = new Set(set);
}

// 提取分组规则：
// 1) 以 - . _ 分隔
// 2) 从末尾开始剔除仅数字或日期样式的token（如 2025、10、202501、20250101、0001）
// 3) 剩余部分按 - 连接作为分组键
function extractGroupKey(name: string): string {
  const tokens = name.split(/[-._]/).filter((t) => t.length > 0);
  // 判断是否数字或常见日期（纯数字）
  const isNumericLike = (t: string) => /^[0-9]+$/.test(t);
  // 从末尾剔除数字token
  let end = tokens.length - 1;
  while (end >= 0 && isNumericLike(tokens[end])) {
    end--;
  }
  if (end < 0) {
    // 全是数字，归为数字索引组
    return "#numeric";
  }
  const groupTokens = tokens.slice(0, end + 1);
  return groupTokens.join("-");
}

type VirtualRow =
  | { type: "group"; key: string; group: string; count: number }
  | { type: "item"; key: string; index: IndexItemType; group: string };

// 构建扁平化虚拟列表：组头 + 组内索引
const virtualRows = computed<VirtualRow[]>(() => {
  const map = new Map<string, IndexItemType[]>();
  items.value.forEach((it) => {
    const g = extractGroupKey(it.name);
    if (!map.has(g)) {
      map.set(g, []);
    }
    map.get(g)!.push(it);
  });
  const groups = Array.from(map.keys()).sort((a, b) => a.localeCompare(b));
  const rows: VirtualRow[] = [];
  for (const g of groups) {
    const list = map.get(g)!;
    rows.push({ type: "group", key: `group:${g}`, group: g, count: list.length });
    if (!collapsedGroups.value.has(g)) {
      for (const it of list) {
        rows.push({ type: "item", key: `item:${g}:${it.name}`, index: it, group: g });
      }
    }
  }
  return rows;
});
</script>

<style lang="less">
.home {
  position: absolute;
  top: 7px;
  left: 7px;
  right: 7px;
  bottom: 7px;

  .home-option {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    justify-content: space-between;
  }

  .home-container {
    position: absolute;
    top: 56px;
    left: 0;
    right: 0;
    bottom: 0;
    /* 让列表充满容器，避免高度塌陷影响滚动 */
    .home-index-items {
      height: 100%;
    }
  }
}

.home-query-status {
  background-color: var(--color-bg-1);
  padding: 7px 0 0 14px;
  border: var(--color-border-2) solid 1px;
  border-radius: 2px;
}

.home-group-header {
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  box-sizing: border-box;

  .left {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 18px;
    font-weight: bold;
  }

  .right {
    color: var(--td-text-color-secondary);
  }
}
</style>
